/*
Copyright (C) 2010 Gerhard Olsson 

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library. If not, see <http://www.gnu.org/licenses/>.
 */

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using System.Globalization;
using System.Reflection;
using System.ComponentModel;

using ZoneFiveSoftware.Common.Data.Fitness;
using ZoneFiveSoftware.Common.Data.Measurement;
using MatrixPlugin;
using MatrixPlugin.Constants;

namespace MatrixPlugin
{
    static class Settings
    {
        public static int Verbose = 0;

        public static double maxRadius = 100;
        public static double currentPointDiffFactor = 4;
        private static string positionGroup = null;
        private static string toolTipFormatString = Preferences.TooltipFormatString;
        private static IActivityCategory selectedCategory = null;
        private static string categoryTmpStr = null;
        private static bool compareToCurrent = true;
        private static bool matchAllPositions = false;

        //Can be set per positiongroup in the xml too
        private static bool includeStoppedTime = true;
        private static bool hideBlankRowsAndColumns = false;
        private static General.TempoType tempoType = General.TempoType.Fastest;
        private static General.DataValue dataValue = General.DataValue.time;
        
        public static double MaxRadius
        {
            get { return maxRadius; }
            set { maxRadius = value; }
        }
        public static double CurrentPointDiffFactor
        {
            get { return currentPointDiffFactor; }
            set { currentPointDiffFactor = value; }
        }

        //As positiongroups are not known when starting up, it easier to use string
        public static string PositionGroup
        {
            get { return positionGroup; }
            set { positionGroup = value; }
        }

        public static string ToolTipFormatString
        {
            get { return toolTipFormatString; }
            set { toolTipFormatString = value; }
        }

        public static IActivityCategory SelectedCategory
        {
             get
             {
                 if (null == selectedCategory && null != categoryTmpStr)
                 {
                     //Race problem at startup: Application is not directly accessible, save temp string
                     selectedCategory = parseCategory(categoryTmpStr);
                     categoryTmpStr = null;
                 }
                 return selectedCategory;
             }
             set { selectedCategory = value; }
        }

        public static bool CompareToCurrent
        {
            get { return compareToCurrent; }
            set { compareToCurrent = value; }
        }

        public static bool MatchAllPositions
        {
            get { return matchAllPositions; }
            set { matchAllPositions = value; }
        }

        public static bool IncludeStoppedTime
        {
            get { return includeStoppedTime; }
            set { includeStoppedTime = value; }
        }

        public static bool HideBlankRowsAndColumns
        {
            get { return hideBlankRowsAndColumns; }
            set { hideBlankRowsAndColumns = value; }
        }

        public static General.TempoType TempoType
        {
            get { return tempoType; }
            set { tempoType = value; }
        }

        public static General.DataValue DataValue
        {
            get { return dataValue; }
            set { dataValue = value; }
        }

        /************************************************/
        public static void ReadOptions(XmlDocument xmlDoc, XmlNamespaceManager nsmgr, XmlElement pluginNode)
        {
            String attr;

            attr = pluginNode.GetAttribute(xmlTags.settingsVersion);
            if (attr.Length > 0) { settingsVersion = (Int16)XmlConvert.ToInt16(attr); }
            attr = pluginNode.GetAttribute(xmlTags.Verbose);
            if (attr.Length > 0) { Verbose = (Int16)XmlConvert.ToInt16(attr); }

            attr = pluginNode.GetAttribute(xmlTags.maxRadius);
            if (attr.Length > 0) { maxRadius = XmlConvert.ToDouble(attr); }
            attr = pluginNode.GetAttribute(xmlTags.currentPointDiffFactor);
            if (attr.Length > 0) { currentPointDiffFactor = XmlConvert.ToDouble(attr); }
            attr = pluginNode.GetAttribute(xmlTags.toolTipFormatString);
            if (attr.Length > 0) { toolTipFormatString = attr; }
            attr = pluginNode.GetAttribute(xmlTags.positionGroup);
            if (attr.Length > 0) { positionGroup = attr; }
            attr = pluginNode.GetAttribute(xmlTags.selectedCategory);
            if (attr.Length > 0) { selectedCategory = parseCategory(attr); }
            attr = pluginNode.GetAttribute(xmlTags.compareToCurrent);
            if (attr.Length > 0) { compareToCurrent = XmlConvert.ToBoolean(attr); }
            attr = pluginNode.GetAttribute(xmlTags.matchAllPositions);
            if (attr.Length > 0) { matchAllPositions = XmlConvert.ToBoolean(attr); }
            attr = pluginNode.GetAttribute(xmlTags.hideBlankRowsAndColumns);
            if (attr.Length > 0) { hideBlankRowsAndColumns = XmlConvert.ToBoolean(attr); }
            attr = pluginNode.GetAttribute(xmlTags.includeStoppedTime);
            if (attr.Length > 0) { includeStoppedTime = XmlConvert.ToBoolean(attr); }
            attr = pluginNode.GetAttribute(xmlTags.TempoType);
            if (attr.Length > 0) { tempoType = (General.TempoType)Enum.Parse(typeof(General.TempoType), attr); }
            attr = pluginNode.GetAttribute(xmlTags.DataValue);
            if (attr.Length > 0) { dataValue = (General.DataValue)Enum.Parse(typeof(General.DataValue), attr); }
        }

        public static void WriteOptions(XmlDocument xmlDoc, XmlElement pluginNode)
        {
            pluginNode.SetAttribute(xmlTags.settingsVersion, XmlConvert.ToString(settingsVersionCurrent));
            pluginNode.SetAttribute(xmlTags.Verbose, XmlConvert.ToString(Verbose));

            pluginNode.SetAttribute(xmlTags.maxRadius, XmlConvert.ToString(maxRadius));
            pluginNode.SetAttribute(xmlTags.currentPointDiffFactor, XmlConvert.ToString(currentPointDiffFactor));
            pluginNode.SetAttribute(xmlTags.toolTipFormatString, toolTipFormatString);
            pluginNode.SetAttribute(xmlTags.positionGroup, positionGroup);
            pluginNode.SetAttribute(xmlTags.selectedCategory, printFullCategoryPath(selectedCategory));
            pluginNode.SetAttribute(xmlTags.compareToCurrent, XmlConvert.ToString(compareToCurrent));
            pluginNode.SetAttribute(xmlTags.matchAllPositions, XmlConvert.ToString(matchAllPositions));
            pluginNode.SetAttribute(xmlTags.includeStoppedTime, XmlConvert.ToString(includeStoppedTime));
            pluginNode.SetAttribute(xmlTags.hideBlankRowsAndColumns, XmlConvert.ToString(hideBlankRowsAndColumns));
            pluginNode.SetAttribute(xmlTags.TempoType, tempoType.ToString());
            pluginNode.SetAttribute(xmlTags.DataValue, dataValue.ToString());
        }

        private static int settingsVersion = 0; //default when not existing
        private const int settingsVersionCurrent = 1;

        private class xmlTags
        {
            public const string settingsVersion = "settingsVersion";
            public const string Verbose = "Verbose";

            public const string maxRadius = "maxRadius";
            public const string currentPointDiffFactor = "currentPointDiffFactor";
            public const string toolTipFormatString = "toolTipFormatString";
            public const string positionGroup = "positionGroup";
            public const string selectedCategory = "selectedCategory";
            public const string compareToCurrent = "compareToCurrent";
            public const string matchAllPositions = "matchAllPositions";
            public const string includeStoppedTime = "includeStoppedTime";
            public const string hideBlankRowsAndColumns = "hideBlankRowsAndColumns";
            public const string TempoType = "TempoType";
            public const string DataValue = "DataValue";
        }

        private static string printFullCategoryPath(IActivityCategory selectedCategory)
        {
            String str = "";
            bool first = true;
            while (selectedCategory != null)
            {
                if (first) first = false;
                else str = "|" + str;
                str = selectedCategory.Name + str;
                selectedCategory = selectedCategory.Parent;
            }
            return str;
        }
        private static IActivityCategory parseCategory(string p)
        {
            if (p == null || p.Equals("")) return null;
            string[] ps = p.Split('|');
            IActivityCategory cat = null;
            if (null == Plugin.GetApplication().Logbook)
            {
                //Cannot parse right now, save value for later
                categoryTmpStr = p;
            }
            else
            {
                cat = getCategory(ps, 0, Plugin.GetApplication().Logbook.ActivityCategories);
            }
            return cat;
        }
        public static IActivityCategory getCategory(string[] ps, int p, IEnumerable<IActivityCategory> iList)
        {
            if (iList == null) return null;
            foreach (IActivityCategory category in iList)
            {
                if (category.Name.Equals(ps[p]))
                {
                    if (p == ps.Length - 1)
                    {
                        return category;
                    }
                    return getCategory(ps, p + 1, category.SubCategories);
                }
            }
            return null;
        }
    }
}
